﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using BTM_Client_Application.SupportClasses;
using GMap.NET;
using GMap.NET.MapProviders;
using GMap.NET.WindowsPresentation;

namespace BTM_Client_Application
{
    partial class MapControl
    {
        private GMapPolygon _miniMapPolygon = new GMapPolygon(new PointLatLng[0]);
        private int _zIndex;
        private ToolTip _miniMapTooltip;
        private readonly TimeSpan _aniDuration = new TimeSpan(0, 0, 0, 0, 200);

        private void ChangeMiniMapSelectedZone(RectLatLng newZone)
        {
            var points = new List<PointLatLng>
                {
                    newZone.LocationTopLeft,
                    new PointLatLng(newZone.Top, newZone.Right),
                    newZone.LocationRightBottom,
                    new PointLatLng(newZone.Bottom, newZone.Left),
                };
            var p = new GMapPolygon(points);
            p.RegenerateShape(MiniMap);

            p.Shape = new Border
            {
                Background = new SolidColorBrush(Colors.Black) { Opacity = 0.3 },
                BorderBrush = Res.AccentBlueBrush,
                BorderThickness = new Thickness(2, 2, 2, 2),
                Width = (p.Shape as Path).Data.Bounds.Width,
                Height = (p.Shape as Path).Data.Bounds.Height,
            };
            _miniMapPolygon = p;
            MiniMap.Markers[_zIndex] = p;
        }

        private void InitMiniMap()
        {
            _miniMapTooltip = new ToolTip();
            ShowMiniMapButton.ToolTip = _miniMapTooltip;
            MiniMap.MapProvider = GoogleMapProvider.Instance;
            MiniMap.ShowCenter = false;
            MiniMap.SetZoomToFitRect(BelarusBounds);
            MiniMap.Markers.Add(_miniMapPolygon);
            _zIndex = _miniMapPolygon.ZIndex;
            MiniMap.MouseDown += MiniMapOnMouseDown;
            MiniMap.MouseMove += MiniMapOnMouseMove;
            MiniMap.MouseUp += MiniMapOnMouseUp;
            MiniMap.MouseLeave += MiniMapOnMouseLeave;
            MiniMap.IsVisibleChanged += MiniMapOnIsVisibleChanged;
        }

        private void MiniMapOnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
        {
            if ((bool)dependencyPropertyChangedEventArgs.NewValue)
            {
                Res.MakeOpacityAnimation(true, MiniMap, _aniDuration, true, Res.ScaleCenter.RightTopCorner);
            }
        }

        private Point _miniMapMouseDownPosition;
        private GPoint _polygonStartPosition;
        private bool _allowMove;

        private void MiniMapOnMouseDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
        {
            if (_miniMapPolygon.Shape as Path != null)
                return;
            GmapBox.OnPositionChanged -= GmapBoxOnOnPositionChanged;
            if (mouseButtonEventArgs.LeftButton != MouseButtonState.Pressed)
                return;
            _allowMove = true;
            if (!_miniMapPolygon.Shape.IsMouseOver)
            {
                var info = (_miniMapPolygon.Shape as Border);
                var p = Mouse.GetPosition(MiniMap);
                _miniMapPolygon.Position = MiniMap.FromLocalToLatLng((int)(p.X - info.Width / 2), (int)(p.Y - info.Height / 2));
                _polygonStartPosition = MiniMap.FromLatLngToLocal(_miniMapPolygon.Position);
            }
            else
            {
                _polygonStartPosition = MiniMap.FromLatLngToLocal(_miniMapPolygon.Position);
            }
            _miniMapMouseDownPosition = Mouse.GetPosition(MiniMap);
        }

        private void MiniMapOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
        {
            var marker = _miniMapPolygon;
            if (mouseEventArgs.LeftButton != MouseButtonState.Pressed || !_allowMove)
                return;

            var p = Mouse.GetPosition(MiniMap);
            var dx = p.X - _miniMapMouseDownPosition.X;
            var dy = p.Y - _miniMapMouseDownPosition.Y;

            marker.Position = MiniMap.FromLocalToLatLng((int)(_polygonStartPosition.X + dx),
                                                                 (int)(_polygonStartPosition.Y + dy));
            GmapBox.Position =
                MiniMap.FromLocalToLatLng((int) ((_polygonStartPosition.X + dx) + (marker.Shape as Border).Width/2),
                                          (int) ((_polygonStartPosition.Y + dy) + (marker.Shape as Border).Height/2));

        }

        private void MiniMapOnMouseUp(object sender, MouseButtonEventArgs mouseButtonEventArgs)
        {
            DenyMove();
        }
        private void MiniMapOnMouseLeave(object sender, MouseEventArgs mouseEventArgs)
        {
            DenyMove();
        }

        private void DenyMove()
        {
            _allowMove = false;
            GmapBox.OnPositionChanged += GmapBoxOnOnPositionChanged;
            ChangeMiniMapSelectedZone(GmapBox.ViewArea);
        }

        private void ShowMiniMapButton_OnClick(object sender, RoutedEventArgs e)
        {
            ChangeShowMiniMapButtonState();
        }

        private void ChangeShowMiniMapButtonState()
        {
            Image im;
            if (MiniMap.IsVisible)
            {
                _miniMapTooltip.Content = Res.Rm.GetString("ShowMiniMap", AliveInfo.CurrentCulture);
                Res.HideWithAnimation(MiniMap, _aniDuration, true, Res.ScaleCenter.RightTopCorner);
                im = new Image { Source = FindResource("ArrowExpandDark") as BitmapImage };
            }
            else
            {
                _miniMapTooltip.Content = Res.Rm.GetString("HideMiniMap", AliveInfo.CurrentCulture);
                MiniMap.Visibility = Visibility.Visible;
                im = new Image { Source = FindResource("ArrowCollapsedDark") as BitmapImage };
            }
            ShowMiniMapButton.Content = im;
        }

        public void UpdateUiLanguage()
        {
            if (!MiniMap.IsVisible)
            {
                _miniMapTooltip.Content = Res.Rm.GetString("HideMiniMap", AliveInfo.CurrentCulture);
            }
            else
            {
                _miniMapTooltip.Content = Res.Rm.GetString("ShowMiniMap", AliveInfo.CurrentCulture);
            }
        }

        private void MiniMap_OnMouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (e.Delta > 0)
            {
                if (GmapBox.Zoom < GmapBox.MaxZoom)
                    GmapBox.Zoom++;
            }
            else if(e.Delta < 0)
            {
                if (GmapBox.Zoom > GmapBox.MinZoom)
                    GmapBox.Zoom--;
            }
        }
    }
}
